import string
import BaseHTTPServer, httplib, SocketServer, urllib, re, os, sys
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from urlparse import urlparse
from classes import MapList
import threading

packetCount = 0

Plugins = {}
PluginsStorage = {}

enabledPluginIcon = ""

class ProxyHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

	def doCommon(self):	
		req = Request(self)
		req.delHeaders("accept-encoding", "host", "proxy-connection")
		
		res = req.getResponse()
		res.delHeader("transfer-encoding")
		res.toClient()
		
	def do_GET(self):
		self.doCommon()

	def do_POST(self):
		self.doCommon()

class Request:
	def __init__(self, proxy):
		self.proxy = proxy
		self.host = proxy.headers.getheader("host")
		self.command = proxy.command
		self.path = proxy.path
		self.headers = proxy.headers.dict
		self.conn = httplib.HTTPConnection(self.host)
		
		if self.command == "POST":
			self.body = self.proxy.rfile.read(\
				int(self.proxy.headers.getheader("content-length")) )
		else:
			self.body = None

                for i in Plugins:
                        if 'edit_REQUEST' in dir(Plugins[i]):
                                Plugins[i].edit_REQUEST(self,PluginsStorage[i])
	
	def getHeader(self, k):
		if self.headers.has_key(k):
			return self.headers[k]
		else:
			return None
		
	def setHeader(self, k, v):
		self.headers[k] = v
	
	def setHeaders(self, dict):
		for i in dict.items():
			self.setHeader(i[0], i[1])
	
	def delHeader(self, k):
		if self.headers.has_key(k):
			del self.headers[k]
			
	def delHeaders(self, *list):
		for l in list:
			self.delHeader(l)
	
	def bodyDecode(self):
		m = MapList()
		for b in self.body.split("&"):
			for p in b.split("="):
				if p != "":
					m.add(urllib.unquote_plus(p[0]),
						urllib.unquote_plus(p[1]))
		return m
						
	def bodyEncode(self, mapList):
		body = ""
		for k in mapList.keys():
			for l in mapList.getList(k):
				body += "%s=%s&" % (urllib.quote_plus(k),
									urllib.quote_plus(l))
		if body == "":
			self.body = None
		else:
			self.body = body[:-1]
	
	def getResponse(self):
		if self.body:
			self.headers["content-length"] = str(len(self.body))
			self.conn.request("POST", self.path, self.body, self.headers)
		else:
			self.conn.request("GET", self.path, headers=self.headers)
			
		return Response(self.proxy, self.conn.getresponse())
			
class Response:
	def __init__(self, proxy, server):
		self.proxy = proxy
		self.server = server
		self.status = server.status
		self.body = server.read()
		
		self.headers = MapList()
		for l in server.getheaders():
			self.headers.add(l[0], l[1])

	def getHeader(self, k, index=-1):
		if self.headers.hasKey(k, index):
			return self.headers.get(k, index)
		else:
			return None
		
	def setHeader(self, k, v, index=-1):
		self.headers.set(k, v, index)
		
	def addHeader(self, k, v):
		self.headers.add(k, v)
	
	def addHeaders(self, dict):
		for i in dict.items():
			self.setHeader(i[0], i[1])
	
	def delHeader(self, k):
		if self.headers.hasKey(k):
			self.headers.delMap(k)
			
	def delHeaders(self, *list):
		for l in list:
			self.delHeader(l)
			
	def toClient(self):
                global packetCount
                packetCount+=1
                for i in Plugins:
                        if 'edit_RESPONSE' in dir(Plugins[i]):
                                Plugins[i].edit_RESPONSE(self,PluginsStorage[i])

		self.proxy.send_response(self.status)
		for k in self.headers.keys():
			for l in self.headers.getList(k):
				self.proxy.send_header(k, l)
		self.proxy.end_headers()

		#if("content-type" in self.headers.keys()):
		#	if('text/html' in self.headers.getList("content-type")[0]):
		#		self.body = re.sub("</html>","<div style='position:fixed;left:0px;top:0px;width:100%;background-color:white;'><center><img src='http://lostboy.net/wp-content/uploads/2009/05/defcon.png'></center></div></html>",self.body)
		
		#self.body = re.sub("</html>","<div style='position:fixed;left:0px;top:0px;width:100%;background-color:white;'><center><img src='http://lostboy.net/wp-content/uploads/2009/05/defcon.png'></center></div></html>",self.body)
		self.proxy.wfile.write(self.body)

class ThreadingHTTPServer(SocketServer.ThreadingTCPServer, BaseHTTPServer.HTTPServer):
    pass

def startProxy(port = 9999, HandlerClass = ProxyHTTPRequestHandler, ServerClass = ThreadingHTTPServer):
     ServerAddress = ('', port)
     httpd = ServerClass(ServerAddress, HandlerClass, bind_and_activate=False)
     httpd.allow_reuse_address = 1
     httpd.server_bind()
     httpd.server_activate()
     return httpd

class MyHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        try:
            global packetCount

            pluginLinks = ""
            pluginHTML = ""
            pluginTitle = ""
            for i in Plugins:
                pluginLink = Plugins[i].web
                if pluginLink[1]!="/":
                    pluginLink="/"+pluginLink

                if self.path.startswith(pluginLink):
                    if 'handle_HTTP_RESPONSE' in dir(Plugins[i]):
                        Plugins[i].handle_HTTP_RESPONSE(self,PluginsStorage[i])
                        pluginHTML="<div style='padding:8px'>"
                        pluginHTML+=Plugins[i].do_PAGE(PluginsStorage[i])
                        pluginHTML+="</div>"
                        pluginTitle=Plugins[i].name

                if PluginsStorage[i].enabled:
                    pluginLinks+="<img src='"+enabledPluginIcon+"' width=16px height=16px>\t"
                pluginLinks+="<a href='"+pluginLink+"'>"+i+"</a><br>"

            self.send_response(200)
            self.send_header('Content-type',	'text/html')
            self.end_headers()
            self.wfile.write("""
            <html><div style='width:25%;height:100%;float:left;border:1px solid grey'>
            <center><h1>PMOD</h1></center>
            <span style='padding:8px'>Packets Proxied: """+str(packetCount)+"""</span><br>
            <div style='padding:8px'>
            """+pluginLinks+"""
            </div>
            </div>""")
            if pluginHTML != "":
                self.wfile.write("""<div style='width:73%;float:right;border:1px solid grey'>
                                 """+pluginHTML+"""
                                 </div></html>""")
        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)
     

    def do_POST(self):
        pass

class ThreadedHTTPServerHTTP(SocketServer.ThreadingMixIn, HTTPServer):
    pass

class storage:
    pass

try:
    print 'initalising plugins...'
    sys.path.append("./plugins")
    lst = os.listdir("plugins")
    for i in lst:
        if 'plugin.py' in i.lower() and not i.endswith("c"):
            p = __import__(i[:-3], None, None, [])
            Plugins[p.name] = p

            s = storage()
            s.enabled = False
            PluginsStorage[p.name] = s
            if 'setup' in dir(Plugins[p.name]):
                Plugins[p.name].setup(storage)

    print 'initalising httpServer...'
    server_address = ('', 80)
    server = ThreadedHTTPServerHTTP(server_address, MyHandler)
    server.socket.setblocking(0)
    print 'initalising proxy...'
    proxyserver = startProxy()
    proxyserver.socket.setblocking(0)
    while 1:
        proxyserver.handle_request()
        server.handle_request()
except KeyboardInterrupt:
    print '^C received, shutting down server'
    server.socket.close()
    proxyserver.socket.close()
